#pragma once
#include "sock.h"
#include <string>
#include <pthread.h>
#include <fstream>
#include <vector>
#include <functional>

class tcpserver;
const std::string room = "./room";

class threadData
{
public:
    threadData(int fd, const std::string &ip, uint16_t port, tcpserver *t)
        : _sockfd(fd), _ip(ip), _port(port), _t(t)
    {
    }

public:
    int _sockfd;
    std::string _ip;
    uint16_t _port;
    tcpserver *_t;
};

class tcpserver
{
public:
    typedef std::function<std::string(std::string &)> func_t;
    tcpserver(uint16_t port, func_t call) : _port(port), _calback(call)
    {
        _listensocket.Socket();
        _listensocket.Bind(_port);
        _listensocket.Listen();
    }
    void Start()
    {
        std::cout << "start now..." << std::endl;
        while (true)
        {
            std::string clientip;
            uint16_t clientport;
            int sockfd = _listensocket.Accept(clientip, clientport);
            if (sockfd < 0)
            {
                std::cout << "Accept error" << std::endl;
                continue;
            }
            std::cout << "Accept over..." << std::endl;
            threadData *Data = new threadData(sockfd, "", 0, this);
            pthread_t tid;
            pthread_create(&tid, nullptr, threadHandler, Data);
        }
    }
    void httpHandler(int fd)
    {
        std::string inbuffer;
        while (true)
        {
            char buffer[1024]{0};
            ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                inbuffer += buffer;
                std::cout << inbuffer << std::endl;
                while(true)
                {
                    std::string message = _calback(inbuffer);
                    if(message == "")
                        break;
                    send(fd, message.c_str(), message.size(), 0);
                }
            }
            else
            {
                break;
            }
        }

        close(fd);
    }
    static void *threadHandler(void *args)
    {
        pthread_detach(pthread_self());
        threadData *td = (threadData *)args;
        td->_t->httpHandler(td->_sockfd);
        delete td;
        return nullptr;
    }

private:
    Sock _listensocket;
    uint16_t _port;
    func_t _calback;
};
